"""
字典管理
"""

from datetime import datetime
import time
from typing import List

from fastapi import Depends
from fastapi_pagination.bases import AbstractPage
from fastapi_pagination.ext.databases import paginate
from sqlalchemy import insert, select, update

from forward.api.admin.schemas.setting import (
    SettingDictTypeOutSchema,
    SettingDictTypeListInSchema,
    SettingDictTypeAddInSchema,
    SettingDictTypeEditInSchema,
    SettingDictTypeDeleteInSchema,
    SettingDictTypeDetailInSchema,
    SettingDictDataListInSchema,
    SettingDictDataOutSchema,
    SettingDictDataDetailInSchema,
    SettingDictDataAddInSchema,
    SettingDictDataEditInSchema,
    SettingDictDataDeletelInSchema,
)
from forward.dependencies.database import db
from forward.model.tables.setting import DictDataModel, DictTypeModel


class SettingDictTypeService:

    async def all(self):
        """字典类型所有"""
        all_dict = await db.fetch_all(
            select(DictTypeModel)
            .where(DictTypeModel.is_delete == 0)
            .order_by(DictTypeModel.id.desc())
        )
        return [
            SettingDictTypeOutSchema.model_validate(dict, from_attributes=True)
            for dict in all_dict
        ]

    async def list(self, list_in: SettingDictTypeListInSchema):
        """字典类型列表"""
        where = [DictTypeModel.is_delete == 0]
        if list_in.dictType is not None:
            where.append(DictTypeModel.dict_type.like(f"%{list_in.dictType}%"))
        if list_in.dictName is not None:
            where.append(DictTypeModel.dict_name.like(f"%{list_in.dictName}%"))
        if list_in.dictStatus is not None:
            where.append(DictTypeModel.dict_status == list_in.dictStatus)
        query = (
            select(DictTypeModel)
            .select_from(DictTypeModel)
            .where(*where)
            .order_by(DictTypeModel.id.desc())
        )

        return await paginate(db, query)

    async def detail(
        self, detail_in: SettingDictTypeDetailInSchema
    ) -> SettingDictTypeOutSchema:
        """字典类型详情"""

        type_detail = await db.fetch_one(
            select(DictTypeModel)
            .select_from(DictTypeModel)
            .where(
                DictTypeModel.id == detail_in.id,
                DictTypeModel.is_delete == 0,
            )
            .limit(1)
        )
        assert type_detail, "字典类型不存在！"
        return SettingDictTypeOutSchema.model_validate(
            type_detail, from_attributes=True
        )

    async def add(self, add_in: SettingDictTypeAddInSchema):
        """字典类型新增"""
        assert not await db.fetch_one(
            select(DictTypeModel.id)
            .select_from(DictTypeModel)
            .where(
                DictTypeModel.dict_name == add_in.dict_name,
                DictTypeModel.is_delete == 0,
            )
        ), "字典名称已存在！"
        assert not await db.fetch_one(
            select(DictTypeModel.id)
            .select_from(DictTypeModel)
            .where(
                DictTypeModel.dict_type == add_in.dict_type,
                DictTypeModel.is_delete == 0,
            )
            .limit(1)
        ), "字典类型已存在！"

        create_dict = dict(add_in)

        await db.execute(insert(DictTypeModel).values(**create_dict))

    async def edit(self, edit_in: SettingDictTypeEditInSchema):
        assert await db.fetch_one(
            select(DictTypeModel.id)
            .select_from(DictTypeModel)
            .where(
                DictTypeModel.id == edit_in.id,
                DictTypeModel.is_delete == 0,
            )
        ), "字典类型不存在！"

        # assert not await db.fetch_one(
        #     select(DictTypeModel.id)
        #     .select_from(DictTypeModel)
        #     .where(
        #         DictTypeModel.dict_name == edit_in.dict_name,
        #         DictTypeModel.is_delete == 0,
        #     )
        # ), "字典名称已存在！"

        # assert not await db.fetch_one(
        #     select(DictTypeModel.id)
        #     .select_from(DictTypeModel)
        #     .where(
        #         DictTypeModel.dict_type == edit_in.dict_type,
        #         DictTypeModel.is_delete == 0,
        #     )
        # ), "字典类型已存在！"

        type_edit = edit_in.model_dump()
        return await db.execute(
            update(DictTypeModel)
            .where(DictTypeModel.id == edit_in.id)
            .values(**type_edit)
        )

    async def delete(self, delete_in: SettingDictTypeDeleteInSchema):
        """
        删除字典类型
        :param delete_in:
        :return:
        """
        await db.execute(
            update(DictTypeModel)
            .where(DictTypeModel.id.in_(delete_in.ids))
            .values(is_delete=1, deleted_time=datetime.now())
        )

    async def get_dict_type_id_by_type(self, dict_type: str) -> int:
        """
        根据字典类型， 返回字典类型的id
        :param dict_type:
        :return:
        """
        type_record = await db.fetch_one(
            select(DictTypeModel)
            .select_from(DictTypeModel)
            .where(
                DictTypeModel.dict_type == dict_type,
                DictTypeModel.is_delete == 0,
            )
        )
        assert type_record, "该字典类型不存在"
        type = SettingDictTypeOutSchema.model_validate(
            type_record, from_attributes=True
        )
        return type.id

    @classmethod
    async def instance(cls):
        return cls()


class SettingDictDataService:
    """
    字典数据服务抽象类
    """

    async def list(
        self, list_in: SettingDictDataListInSchema
    ) -> AbstractPage[SettingDictDataOutSchema]:
        """
        字典数据-列表
        :param list_in:
        :return:
        """
        dict_type_id = await self.dict_type_service.get_dict_type_id_by_type(
            list_in.dict_type
        )
        query = self.get_dict_data_list_query(list_in, dict_type_id)
        return await paginate(db, query)

    async def all(
        self, all_in: SettingDictDataListInSchema
    ) -> List[SettingDictDataOutSchema]:
        """
        字典数据-所有
        :param all_in:
        :return:
        """
        dict_type_id = await self.dict_type_service.get_dict_type_id_by_type(
            all_in.dict_type
        )
        query = self.get_dict_data_list_query(all_in, dict_type_id)
        all_dict = await db.fetch_all(query)
        return [
            SettingDictDataOutSchema.model_validate(dict, from_attributes=True)
            for dict in all_dict
        ]

    def get_dict_data_list_query(
        self, params: SettingDictDataListInSchema, dict_type_id: int
    ):
        """
        all、list的搜索条件一致
        :param params:
        :return:
        """
        where = [
            DictDataModel.is_delete == 0,
            DictDataModel.type_id == dict_type_id,
        ]
        if params.name is not None:
            where.append(DictDataModel.name.like(f"%{params.name}%"))
        if params.value is not None:
            where.append(DictDataModel.value.like(f"%{params.value}%"))
        if params.status is not None:
            where.append(DictDataModel.status == params.status)
        return select(DictDataModel).where(*where).order_by(DictDataModel.id.desc())

    async def detail(
        self, detail_in: SettingDictDataDetailInSchema
    ) -> SettingDictDataOutSchema:
        """
        字典数据-详情
        :param detail_in:
        :return:
        """
        data_detail_record = await db.fetch_one(
            select(DictTypeModel)
            .select_from(DictDataModel)
            .where(
                DictDataModel.id == detail_in.id,
                DictDataModel.is_delete == 0,
            )
            .limit(1)
        )
        assert data_detail_record, "字典数据不存在！"
        return SettingDictDataOutSchema.model_validate(
            data_detail_record, from_attributes=True
        )

    async def add(self, add_in: SettingDictDataAddInSchema):
        """
        字典数据-新增
        :param add_in:
        :return:
        """
        assert not await db.fetch_one(
            select(DictDataModel.id)
            .select_from(DictDataModel)
            .where(
                DictDataModel.name == add_in.name,
                DictDataModel.type_id == add_in.type_id,
                DictDataModel.is_delete == 0,
            )
        ), "字典数据已存在！"
        create_dict = dict(add_in)

        await db.execute(insert(DictDataModel).values(**create_dict))

    async def edit(self, edit_in: SettingDictDataEditInSchema):
        assert await db.fetch_one(
            select(DictDataModel.id)
            .select_from(DictDataModel)
            .where(
                DictDataModel.id == edit_in.id,
                DictDataModel.is_delete == 0,
            )
            .limit(1)
        ), "字典数据不存在！"
        assert not await db.fetch_one(
            select(DictDataModel.id)
            .select_from(DictDataModel)
            .where(
                DictDataModel.name == edit_in.name,
                DictDataModel.is_delete == 0,
            )
            .limit(1)
        ), "字典数据已存在！"
        type_edit = edit_in.model_dump()
        return await db.execute(
            update(DictDataModel)
            .where(DictDataModel.id == edit_in.id)
            .values(**type_edit)
        )

    async def delete(self, delete_in: SettingDictDataDeletelInSchema):
        """
        删除字典数据
        :param delete_in:
        :return:
        """
        await db.execute(
            update(DictDataModel)
            .where(DictDataModel.id.in_(delete_in.ids))
            .values(is_delete=1, deleted_time=datetime.now())
        )

    def __init__(
        self,
        dict_type_service: SettingDictTypeService = Depends(
            SettingDictTypeService.instance
        ),
    ):
        self.dict_type_service: SettingDictTypeService = dict_type_service

    @classmethod
    async def instance(
        cls,
        dict_type_service: SettingDictTypeService = Depends(
            SettingDictTypeService.instance
        ),
    ):
        return cls(dict_type_service)
